package mi.dao;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.Collection;
import java.util.List;
import java.util.Set;

import mi.common.utils.EntityUtil;
import mi.dto.BaseDTO;
import mi.model.BaseModel;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.Criterion;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

/**
 * @ProjectName: [ maven 自动化集成测试系统 ]
 * @Author: [ huanghuanlai ]
 * @CreateTime: [ 2015年5月25日 下午7:16:52 ]
 * @Copy: [ dounine.com ]
 * @Version: [ V1.0 ]
 * @Description: [ CRUD ]
 */
@Repository
public abstract class CrudRepositoryImpl<Model extends BaseModel,DTO extends BaseDTO> implements ICrudRepository<Model,DTO> {
	
	protected SessionFactory sessionFactory;
	
	protected Class<Model> entityClass;
	
	/**
	 * 初始化entityClass对象
	 */
	@SuppressWarnings("unchecked")
	public CrudRepositoryImpl(){
		Type genType = getClass().getGenericSuperclass();
		Type[] params = ((ParameterizedType)genType).getActualTypeArguments();
		entityClass = (Class<Model>)params[0];
		System.out.println(entityClass.getName());
	}
	
	@Autowired
	public void setSessionFactory(SessionFactory sessionFactory) {
		this.sessionFactory = sessionFactory;
	}
	
	public String getEntityTableName(Class<Model> entityClass2){
		return EntityUtil.getEntityNameByTableName(sessionFactory, entityClass2.getName());
	}
	
	public String getEntityTableName(){
		return getEntityTableName(entityClass);
	}
	
	protected Session getSession() {
		return sessionFactory.getCurrentSession();
	}
	
	@Override
	@SuppressWarnings("unchecked")
	public Model find(Model model) {
		return (Model) getSession().get(entityClass, model.getId());
	}

	@Override
	public Integer save(Model model) {
		return (Integer)this.getSession().save(model);
	}

	@Override
	@SuppressWarnings("unchecked")
	public Model findOne(Integer primaryKey) {
		return (Model) this.getSession().get(entityClass, primaryKey);
	}

	@Override
	@SuppressWarnings("unchecked")
	public Iterable<Model> findAll() {
		return this.getSession().createCriteria(entityClass).list();
	}

	@Override
	public Long count(DTO dto) {
		return  (Long) this.getSession().createQuery("select count(*) from "+entityClass.getName()).uniqueResult();
	}

	@Override
	public void delete(Model model) {
		this.getSession().delete(model);
	}

	@Override
	public boolean exists(Integer primaryKey) {
		Object object = this.getSession().get(entityClass, primaryKey);
		return object!=null;
	}

	@Override
	public void edit(Model model) {
		this.getSession().update(model);
	}

	@Override
	@SuppressWarnings("unchecked")
	public Collection<Model> findByPageable(DTO dto) {
		Criteria criteria = this.getSession().createCriteria(entityClass);
		criteria.setFirstResult(dto.getOffset());
		criteria.setMaxResults(dto.getPageSize());
		return criteria.list();
	}

	@Override
	@SuppressWarnings("unchecked")
	public Model findByDTO(DTO dto) {
		return (Model) this.getSession().get(entityClass, dto.getId());
	}

	@Override
	@SuppressWarnings("unchecked")
	public Collection<Model> findByCriteria(DTO dto,Set<Criterion> criterions) {
		Criteria criteria = this.getSession().createCriteria(entityClass);
		if(null!=criterions){
			for(Criterion cri : criterions){
				criteria.add(cri);
			}
		}
		criteria.setFirstResult(dto.getOffset());
		criteria.setMaxResults(dto.getPageSize());
		return criteria.list();
	}

	@Override
	@SuppressWarnings("unchecked")
	public List<Model> select(Model model) {
		Criteria criteria = this.getSession().createCriteria(entityClass);
		return criteria.list();
	}

}
